<template>
  <div id="liao">
    <van-nav-bar
      :title="name"
      left-text="返回"
      left-arrow
      @click-left="onClickLeft"
    />
    <div class="content" ref="contentRef">
      <div v-for="item in list" :key="item._id" class="ls">
        <div :class="item.from == from ? 'right_time' : 'left_time'">
          <span>{{ item.time }}</span>
        </div>
        <div :class="item.from == from ? 'right' : 'left'">
          <span v-if="!item.voice" class="message">
            {{ item.message }}
          </span>
          <button
            v-if="item.voice"
            @click="playAudio(item.voice)"
            class="voice"
            :style="{
              width: 2 + parseInt(item.message) + 'rem',
              height: '2.2rem',
            }"
          >
            <img src="/icon/语音播放left.png" alt="" />
            <span>{{ item.message }}</span>
          </button>
          <img :src="item.from === from ? from_img : to_img" alt="" />
        </div>
      </div>
    </div>
    <div class="footer">
      <div class="yu">
        <img src="/icon/声音.png" alt="" @click="isLu" />
      </div>
      <div
        v-if="islu"
        class="lu"
        @touchstart="data.voice"
        @touchend="data.submit"
      >
        <img src="/icon/wave.png" alt="" />
      </div>
      <input
        v-if="!islu"
        ref="input"
        type="text"
        v-model="inputvalue"
        :class="flag ? 'qi' : 'ting'"
      />
      <div v-if="!islu" :class="flag ? 'yinn' : 'yin'" @touchstart="start">
        <img v-if="!flag" src="/icon/语音转文字.png" alt="" @touchend="end" />
        <img v-if="flag" src="/icon/语音转文字2.png" alt="" />
      </div>
      <button v-if="!inputvalue" class="send1">发送</button>
      <button v-if="inputvalue" class="send" @click="send">发送</button>
    </div>
  </div>
</template>

<script setup>
import axios from "axios";
import { ref, reactive, onMounted, watch, nextTick } from "vue";
import { useRoute } from "vue-router";
import { io } from "socket.io-client";
import Recorder from "js-audio-recorder";
import { useCounterStore } from "../../stores/counter";
const useState = useCounterStore();

const data = reactive({
  //用于存储创建的语音对象
  recorder: null,
  formData: [],
  // 控制录音动画的显示隐藏
  showAnima: false,
  mation: true,
  isHistory: true,
  // 录音时长
  duration: 0,
  submit() {
    data.recorder.pause(); // 暂停录音
    data.timer = null;
    console.log("上传录音"); // 上传录音

    var blob = data.recorder.getWAVBlob(); // 获取 wav 格式音频数据
    var newBlob = new Blob([blob], { type: "audio/wav" });

    // 转成 base64 编码
    var reader = new FileReader();
    reader.onload = function (e) {
      var base64 = e.target.result.split(",")[1]; // 获取 Base64 字符串部分

      // 计算出录音时长
      data.duration = Math.ceil((new Date() - data.duration) / 1000);

      // 发送给后端的方法
      let obj = {
        from: from,
        to: to,
        message: data.duration,
        voice: base64,
        time: new Date().toLocaleString(),
      };
      socket.emit("message", JSON.stringify(obj));

      // 在发送后停止和销毁录音实例
      data.handleStop();
      data.handleDestroy();

      // 更新数据
      getlist()
        .then((updatedList) => {
          console.log("Updated list:", updatedList);
        })
        .catch((error) => {
          console.error("Error fetching updated list:", error);
        });
    };
    reader.readAsDataURL(newBlob); // 使用 Data URL 方式读取
  },
  // 录音按钮的点击事件
  voice() {
    //实例化语音对象
    data.recorder = new Recorder({
      sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
      sampleRate: 16000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000
      numChannels: 1, // 声道，支持 1 或 2， 默认是1
    });

    //记录开始录音的时间
    data.duration = new Date();
    Recorder.getPermission().then(
      () => {
        console.log("开始录音");
        data.recorder.start(); // 开始录音
      },
      (error) => {
        console.log(`${error.name} : ${error.message}`);
      }
    );
  },
  handleStop() {
    console.log("停止录音");
    data.recorder.stop(); // 停止录音
    data.mation = false;
  },
  handleDestroy() {
    console.log("销毁实例");
    if (data.recorder) {
      data.recorder.destroy(); // 毁实例
    }
  },
});

const base64ToArrayBuffer = (base64) => {
  const binaryString = window.atob(base64);
  const len = binaryString.length;
  const bytes = new Uint8Array(len);
  for (let i = 0; i < len; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return bytes.buffer;
};

// Convert ArrayBuffer to Blob URL
const bufferToBlobUrl = (arrayBuffer) => {
  // Use the correct MIME type for your audio format
  const blob = new Blob([arrayBuffer], { type: "audio/wav" }); // Adjust MIME type if needed
  return URL.createObjectURL(blob);
};

// Play audio from Base64 string
const playAudio = (base64Audio) => {
  // Convert Base64 to ArrayBuffer
  const arrayBuffer = base64ToArrayBuffer(base64Audio);

  // Create a Blob URL from ArrayBuffer
  const url = bufferToBlobUrl(arrayBuffer);

  const audio = new Audio(url);
  audio.play().catch((error) => {
    console.error("Error playing audio:", error);
  });

  audio.addEventListener("ended", () => {
    URL.revokeObjectURL(url); // Clean up Blob URL
  });
};

// 是否是录音状态
const islu = ref(false);
const isLu = () => {
  islu.value = !islu.value;
};

const route = useRoute();
// 获取聊天室div
const contentRef = ref(null);
const onClickLeft = () => history.back();

const socket = io("http://localhost:4000", {
  connected: true, // 是否自动重连
  reconnectionAttempts: 3, // 重连尝试次数
  reconnectionDelay: 1000, // 重连延迟时间（毫秒）
  reconnectionDelayMax: 5000, // 最大重连延迟时间（毫秒）
  pingTimeout: 5000, // 5秒未收到 'pong' 则认为连接断开
  pingInterval: 2000, // 2秒发送一次心跳
  pingMsg: "custom-ping", // 使用自定义的心跳消息
});

const inputvalue = ref("");
const name = route.query.name;
const from = useState.info._id;
const to = route.query.id;
const from_img = useState.info.imgsrc;
const to_img = route.query.imgsrc;
const list = ref([]);

// 获取数据
const getlist = async () => {
  try {
    const response = await axios.get(
      `http://localhost:3000/message/get_message?from=${from}&to=${to}&timestamp=${new Date().getTime()}`
    );
    if (response.data.code === 200) {
      list.value = response.data.data;
    } else {
      console.log("请求失败");
    }
  } catch (error) {
    console.error("请求失败:", error);
  }
};

const input = ref(null);
let time = ref(null);
let flag = ref(false);
const start = () => {
  time = setTimeout(() => {
    startRecognition();
    flag.value = true;
    console.log("开始识别");
    input.value.focus();
  }, 500);
};

const end = () => {
  flag.value = false;
  recognition.stop();
  console.log("停止识别");
  clearInterval(time);
};

const recognition = new (window.SpeechRecognition ||
  window.webkitSpeechRecognition)();
recognition.continuous = false; // 是否连续识别
recognition.lang = "zh-CN"; // 识别语言(中文)
recognition.interimResults = true; // 是否返回临时结果
recognition.maxAlternatives = 1; // 返回结果的最大数量

const send = async () => {
  let obj = {
    from: from,
    to: to,
    message: inputvalue.value,
    voice: "",
    time: new Date().toLocaleString(),
  };
  socket.emit("message", JSON.stringify(obj));
  inputvalue.value = "";
  await getlist();
};

onMounted(() => {
  socket.on("message", (newmessage) => {
    console.log(newmessage);
    getlist();
  });
  getlist();
  recognition.onresult = (event) => {
    const text = event.results[0][0].transcript;
    inputvalue.value = text;
  };
});

const startRecognition = () => {
  recognition.start(); // 开始识别
};

// 监听list，自动滚到到底部
watch(
  () => list,
  () => {
    nextTick(() => {
      if (list.value.length > 0) {
        contentRef.value.lastElementChild.scrollIntoView();
      } else {
        return false;
      }
    });
  },
  {
    deep: true, //深度监听
  }
);
</script>

<style scoped>
* {
  margin: 0;
  padding: 0;
}

#liao {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.top {
  width: 100%;
  height: 3rem;
  border-bottom: 1px solid #000;
}
.content {
  width: 100%;
  height: 85.7%;
  background-image: url("../../../public/room.png");
  background-size: cover;
  overflow: hidden;
  overflow-y: auto;
  border-top: 1px solid black;
}

.ls {
  position: relative;
}

.right_time {
  width: 100%;
  height: 1rem;
  text-align: right;
  position: absolute;
  margin-top: -1.3rem;
  right: 1rem;
}

.left_time {
  width: 100%;
  height: 1rem;
  text-align: left;
  position: absolute;
  margin-top: -1.2rem;
  margin-left: 1rem;
}

.footer {
  width: 100%;
  height: 8%;
  background-color: #ececec;
  display: flex;
}

.ting {
  width: 55%;
  height: 2rem;
  background-color: #fff;
  border-radius: 1.2rem;
  margin-left: 0.5rem;
  margin-top: 3%;
  border: none;
  text-indent: 1rem;
  font-size: 1.2rem;
  caret-color: #159604;
}

.qi {
  width: 55%;
  height: 2rem;
  background-color: #fff;
  border-radius: 1.2rem;
  margin-left: 0.5rem;
  margin-top: 3%;
  border: none;
  text-indent: 1rem;
  font-size: 1.2rem;
  caret-color: #159604;
  box-shadow: 0px 0px 5px #159604;
}

.footer img {
  width: 1.8rem;
  height: 1.8rem;
  margin-top: 0.2rem;
  margin-left: 0.1rem;
}

.yu {
  width: 2rem;
  height: 2rem;
  margin-left: 0.5rem;
  margin-top: 0.7rem;
}

.yin {
  width: 2rem;
  height: 2rem;
  margin-left: 0.5rem;
  margin-top: 0.7rem;
  border-radius: 50%;
}

.yinn {
  width: 2rem;
  height: 2rem;
  margin-left: 0.5rem;
  margin-top: 0.7rem;
  border-radius: 50%;
  background-color: #159604;
  color: white;
}

.send {
  width: 5rem;
  height: 2.2rem;
  border: none;
  background-color: #0758d0;
  color: white;
  text-align: center;
  font-size: 1.2rem;
  margin-top: 0.7rem;
  border-radius: 0.3rem;
  margin-right: 1rem;
  margin-left: 0.5rem;
}

.send1 {
  width: 5rem;
  height: 2.2rem;
  border: none;
  background-color: #b0baca;
  color: white;
  text-align: center;
  font-size: 1.2rem;
  margin-top: 0.7rem;
  border-radius: 0.3rem;
  margin-right: 1rem;
  margin-left: 0.5rem;
}

.right {
  text-align: right;
  margin-top: 10%;
}

.right img {
  width: 2.5rem;
  height: 2.5rem;
  float: right;
  margin-right: 1rem;
  border-radius: 0.3rem;
}

.right .message {
  display: inline-block;
  padding: 0.5rem 0.5rem;
  background-color: #44f02d;
  max-width: 13rem;
  white-space: wrap;
  overflow-wrap: break-word;
  text-align: left;
  border-radius: 0.3rem;
  margin-right: 1rem;
}

.left {
  text-align: left;
  margin-top: 10%;
}

.left img {
  width: 2.5rem;
  height: 2.5rem;
  float: left;
  margin-left: 1rem;
  border-radius: 0.3rem;
}

.left .message {
  display: inline-block;
  padding: 0.5rem 0.5rem;
  background-color: #e9e7e7;
  max-width: 13rem;
  white-space: wrap;
  overflow-wrap: break-word;
  text-align: left;
  border-radius: 0.3rem;
  margin-left: 1rem;
}

.lu {
  width: 64%;
  height: 2rem;
  background-color: #ffffff;
  border: 1px solid rgb(194, 194, 194);
  border-radius: 1rem;
  margin-left: 0.5rem;
  margin-top: 0.7rem;
}

.lu img {
  width: 100%;
  height: 100%;
}

.left .voice {
  display: inline-block;
  text-indent: 1rem;
  max-width: 13rem;
  min-width: 5rem;
  background-color: #e9e7e7;
  white-space: wrap;
  text-align: left;
  border-radius: 0.3rem;
  margin-left: 1rem;
  border: none;
  overflow: hidden;
  line-height: 1.8rem;
}

.left .voice span {
  float: left;
}

.left .voice img {
  float: left;
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.2rem;
}

.right .voice {
  display: inline-block;
  text-indent: 1rem;
  max-width: 13rem;
  min-width: 5rem;
  background-color: #44f02d;
  white-space: wrap;
  text-align: left;
  border-radius: 0.3rem;
  margin-right: 1rem;
  border: none;
  overflow: hidden;
  line-height: 1.8rem;
}

.right .voice img {
  float: right;
  /* 反转 */
  transform: rotateY(180deg);
  width: 1.5rem;
  height: 1.5rem;
  margin-top: 0.2rem;
  margin-left: 0.5rem;
}

.right .voice span {
  float: right;
}
</style>